package com.example.personalaccount.service.impl;

import com.example.personalaccount.dto.ClauseDto;
import com.example.personalaccount.entity.Account;
import com.example.personalaccount.entity.Clause;
import com.example.personalaccount.entity.User;
import com.example.personalaccount.handler.SecurityGetUserUtil;
import com.example.personalaccount.repository.AccountRepository;
import com.example.personalaccount.repository.ClauseRepository;
import com.example.personalaccount.service.ClauseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service("clauseService")
public class ClauseServiceImpl implements ClauseService {

    @Autowired
    private ClauseRepository clauseRepository;

    @Autowired
    private SecurityGetUserUtil securityGetUserUtil;

    @Autowired
    private AccountRepository accountRepository;

    @Override
    public Clause getClause(String id) {
        return clauseRepository.findById(id).orElse(null);
    }

    @Override
    public List<Clause> getClauseByAccountId(String id) {
        User user = securityGetUserUtil.getUser();
        List<Clause> clauses = clauseRepository.getClausesByUserId(user.getId());
        return clauses;
    }

    @Override
    public List<Clause> getClauseByDate(LocalDate dateTime) {
        User user = securityGetUserUtil.getUser();
        List<Clause> outClauses = new ArrayList<>();
        List<Clause> clauses = clauseRepository.getClausesByUserId(user.getId());
        for (Clause clause : clauses) {
            if (clause.getTimeStamp().getYear() == dateTime.getYear()
                    && clause.getTimeStamp().getDayOfYear() == dateTime.getDayOfYear())
            {
                outClauses.add(clause);
            }
        }
        return outClauses;
    }

    @Override
    public List<Clause> getClauseByFlag(boolean flag) {
        User user = securityGetUserUtil.getUser();
        List<Clause> clauses = clauseRepository.getClausesByUserId(user.getId());
        for (Clause clause : clauses) {
            if (clause.isFlag()!=flag)
            {
                clauses.remove(clause);
            }
        }

        return clauses;
    }

    @Override
    public List<Clause> getClauseByFunc(String func) {
        User user = securityGetUserUtil.getUser();
        return clauseRepository.getClausesByUserIdAndFuncContaining(user.getId(),func);
    }

    @Override
    public Clause create(ClauseDto clauseDto) {
        User user = securityGetUserUtil.getUser();
        Account account = accountRepository.getAccountByUserId(user.getId());
        if (account.getAccounts().containsValue(clauseDto.getOriginAccount()) == false)
        {
            throw new NullPointerException("your havent this account please check the originAccount");
        }
        clauseDto.setTimeStamp(clauseDto.getTimeStamp() == null ? LocalDateTime.now() : clauseDto.getTimeStamp());
        Clause clause = new Clause(null, user.getId()
                ,clauseDto.isFlag()
                ,clauseDto.getTimeStamp()
                ,clauseDto.isFlag() ? clauseDto.getTimeStamp()+" "+clauseDto.getOriginAccount()+"支付给了"+clauseDto.getDestinationAccount()+" "+clauseDto.getAmount()+"元":clauseDto.getTimeStamp()+" "+clauseDto.getDestinationAccount()+"支付给了"+clauseDto.getOriginAccount()+" "+clauseDto.getAmount()+"元"
                ,clauseDto.getRemark()
                ,account.getAccounts().entrySet().stream().collect(Collectors.toMap(entity-> entity.getValue(), entity-> entity.getKey())).get(clauseDto.getOriginAccount())
                ,clauseDto.getOriginAccount()
                ,clauseDto.getDestinationAccount(),clauseDto.getAmount()
                ,true);
        Clause save = clauseRepository.save(clause);
        account.getExpends().add(save.getId());
        accountRepository.save(account);
        return save;
    }

    @Override
    public Clause update(ClauseDto clauseDto) {
        User user = securityGetUserUtil.getUser();
        Account account = accountRepository.getAccountByUserId(user.getId());
        Clause clause = new Clause(null, user.getId()
                ,clauseDto.isFlag(),clauseDto.getTimeStamp()
                ,clauseDto.getDetail(),clauseDto.getRemark()
                ,clauseDto.getFunc(),clauseDto.getOriginAccount()
                ,clauseDto.getDestinationAccount(),clauseDto.getAmount()
                ,clauseDto.isStatus());
        return clause;
    }

    @Override
    public Clause delete(String id) {
        Clause clause = clauseRepository.findById(id).orElse(null);
        if (Objects.isNull(clause)) { throw new IllegalArgumentException ("账单为空") ;}
        clauseRepository.delete(clause);
        return clause;
    }

    @Override
    public List<Clause> getClauseByYear(int year, boolean flag) {
        List<Clause> clauses = new ArrayList<>();
        List<Clause> all = clauseRepository.getClausesByUserId(securityGetUserUtil.getUser().getId());
        for (Clause clause : all) {
            if (clause.getTimeStamp().getYear() == year && clause.isFlag() == flag) {
                clauses.add(clause);
            }
        }
        return clauses;
    }

    @Override
    public List<Clause> getClauseByDay(int date, boolean flag) {
        List<Clause> clauses = new ArrayList<>();
        List<Clause> all = clauseRepository.getClausesByUserId(securityGetUserUtil.getUser().getId());
        for (Clause clause : all) {
            if (clause.getTimeStamp().getMonth() == LocalDate.now().getMonth()
                    && clause.getTimeStamp().getDayOfMonth() == date && clause.isFlag() == flag) {
                clauses.add(clause);
            }
        }
        return clauses;
    }

    @Override
    public List<Clause> getClauseByMonth(int month, boolean flag) {
        List<Clause> clauses = new ArrayList<Clause>();
        List<Clause> all = clauseRepository.getClausesByUserId(securityGetUserUtil.getUser().getId());
        for (Clause clause : all) {
            if (clause.getTimeStamp().getMonthValue() == month && clause.isFlag() == flag) {
                clauses.add(clause);
            }
        }
        return clauses;
    }

    @Override
    public List<Clause> getClauseByRange(LocalDateTime startTime, LocalDateTime endTime) {
        List<Clause> clauses = new ArrayList<>();
        List<Clause> all = clauseRepository.getClausesByUserId(securityGetUserUtil.getUser().getId());
        for (Clause clause : all) {
            if (clause.getTimeStamp().isAfter(startTime) && clause.getTimeStamp().isBefore(endTime)) {
                clauses.add(clause);
            }
        }
        return clauses;
    }
}
